package service

import (
	"encoding/json"
	"errors"
	"fmt"
	"gitee.com/zxs-micro/zxs-micro-business/grpc/businesses"
	"gitee.com/zxs-micro/zxs-micro-business/grpc/businesses/impl"
	busspb "gitee.com/zxs-micro/zxs-micro-business/protos/businesses"
	"gitee.com/zxs-micro/zxs-micro-common/grpc"
	commonutil "gitee.com/zxs-micro/zxs-micro-common/grpc/common/utils"
	"gitee.com/zxs-micro/zxs-micro-common/log"
	"gitee.com/zxs-micro/zxs-micro-fuwufaxian/grpc/fwfxserver"
	"gitee.com/zxs-micro/zxs-micro-fuwufaxian/model"
	"github.com/spf13/viper"
	"net"
	"os"
	"os/signal"
	"strings"
	"sync"
	"syscall"
	"time"
)

type BusinessService struct {
	busLock  sync.Mutex
	sigs     chan os.Signal
	buss     *businesses.BusinessService
	selfFunc impl.MicroBusinessFunc
	fxaddr   string
	auths    map[string]model.Fuwu
}

func GetNewBusinessService(f1 impl.MicroBusinessFunc) (*BusinessService, error) {
	if f1 == nil {
		return nil, errors.New("必须输入正确的业务系统应用方法！")
	}
	//此处方法仅作为参数输入，在创建grpc服务时再进行初始化即可。
	b := new(BusinessService)
	b.selfFunc = f1
	return b, nil
}

func (s *BusinessService) Start() {

	conf := GetBusinessConfig()
	selfport := viper.GetString("server.port")
	if selfport == "" {
		//业务服务需要在启动之前设置好配置文件。
		panic("请先设置正确的配置文件！")
	}
	addr := ":" + selfport

	ctx, err := net.Listen("tcp", addr)
	if err != nil {
		log.Log.Errorf("创建grpc服务失败：%s", err.Error())
		panic(err)
		return
	}

	grpcserver, err := grpc.NewGrpcServer(ctx, conf)
	if err != nil {
		log.Log.Errorf("创建grpc服务失败：%s", err.Error())
		panic(err)
		return
	}

	s.buss = businesses.NewBusinessService(s.selfFunc)
	s.buss.ServerType = viper.GetString("server.type")
	s.buss.LocalIp = viper.GetString("server.faxian.localip")
	s.buss.LocalPort = selfport

	busspb.RegisterBusinessesServer(grpcserver.Server(), s.buss)

	var servErr = make(chan error)
	go func() {
		err := grpcserver.Start()
		if err != nil {
			log.Log.Errorf("启动业务系统服务时出现错误：%s", err.Error())
		}
		servErr <- err
	}()

	go func() {
		<-time.After(time.Second)
		log.Log.Info("向服务发现注册自己！")
		var sid = ""
		var fxaddr = viper.GetString("faxian.address")
		s.fxaddr = fxaddr
		var selfip = s.buss.LocalIp
		fx, err := fwfxserver.GenerateFwfxClients(fxaddr)
		if err != nil {
			servErr <- err
			return
		}

		sid, err = fx.InjectNewServer(selfip+":"+selfport, "", s.buss.ServerType)
		//fmt.Println(err)
		if err == nil {
			s.buss.SelfId = sid
			log.Log.Info("向服务发现注册自己成功！自己的ID是：", sid)
		} else {
			servErr <- err
			return
		}

		//获取可用的auth
		bs, err := fx.GetExistServer("auths")
		if err == nil {
			m := make(map[string]map[string]model.Fuwu)
			err = json.Unmarshal(bs, &m)
			if err == nil {
				var ok bool
				s.auths, ok = m["auths"]
				if ok {
					//所有链接全部创建完毕以后，启动自身func
					if err = s.selfFunc.Init(); err != nil {
						log.Log.Errorf("初始化业务代码时发生错误！错误为%s\n", err.Error())
						servErr <- err
					}
					return
				}
				err = errors.New("获得的服务参数不正确，请检查服务列表返回值类型。")
			}
		}
		log.Log.Errorf("查找可用的auth服务出错：%s\n", err.Error())
		servErr <- err
		return
	}()

	log.Log.Infof("业务系统服务已启动！")
	s.sigs = make(chan os.Signal, 1)
	signal.Notify(s.sigs, syscall.SIGINT, syscall.SIGTERM)
	select {
	case <-s.sigs:
		log.Log.Info("业务系统服务关闭.....")
	case shuterr := <-servErr:
		log.Log.Error(shuterr)
		log.Log.Error("由于出现错误，业务系统服务关闭......")
	}
	os.Exit(0)
}

func (s *BusinessService) Shutdown(f bool) {
	signal.Stop(s.sigs)
	fmt.Println("业务系统服务关闭.....")
	os.Exit(0)
}

func (s *BusinessService) GetFXaddr() string {
	return s.fxaddr
}

func (s *BusinessService) GetLoginAddr() string {
	ind := commonutil.GetRandomInt(len(s.auths))
	for _, v := range s.auths {
		if 0 == ind {
			return strings.Split(v.RemoteIp, "/")[0]
		}
		ind--
	}
	return ""
}

func (s *BusinessService) SelfExec(token string, params [][]byte) ([]byte, error) {
	return s.buss.SelfExec(token, params)
}
